using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;

namespace SnakeGame
{
    /// <summary>
    /// 移动方向枚举
    /// </summary>
    public enum Direction
    {
        None,
        Up,
        Down,
        Left,
        Right
    }

    /// <summary>
    /// 游戏状态枚举
    /// </summary>
    public enum GameState
    {
        NotStarted,
        Playing,
        Paused,
        GameOver
    }

    /// <summary>
    /// 游戏难度枚举
    /// </summary>
    public enum GameDifficulty
    {
        Easy,
        Medium,
        Hard
    }

    /// <summary>
    /// 蛇身体节点类
    /// </summary>
    public class SnakeNode
    {
        public Point Position { get; set; }
        public bool IsHead { get; set; }

        public SnakeNode(Point position, bool isHead = false)
        {
            Position = position;
            IsHead = isHead;
        }
    }

    /// <summary>
    /// 蛇类
    /// </summary>
    public class Snake
    {
        public List<SnakeNode> Body { get; private set; }
        public Direction Direction { get; set; }
        public Direction NextDirection { get; set; }

        public Snake()
        {
            Body = new List<SnakeNode>();
            Direction = Direction.Right;
            NextDirection = Direction.Right;
            InitializeSnake();
        }

        /// <summary>
        /// 初始化蛇的身体
        /// </summary>
        private void InitializeSnake()
        {
            Body.Clear();
            // 在中心位置创建蛇，初始长度为3
            Point center = new Point(15, 10); // 假设游戏区域为30x20
            Body.Add(new SnakeNode(center, true)); // 蛇头
            Body.Add(new SnakeNode(new Point(center.X - 1, center.Y)));
            Body.Add(new SnakeNode(new Point(center.X - 2, center.Y)));
        }

        /// <summary>
        /// 移动蛇
        /// </summary>
        public void Move()
        {
            // 更新方向
            Direction = NextDirection;

            // 获取蛇头位置
            Point headPosition = Body[0].Position;
            Point newHeadPosition = GetNewHeadPosition(headPosition);

            // 移动身体
            for (int i = Body.Count - 1; i > 0; i--)
            {
                Body[i].Position = Body[i - 1].Position;
            }

            // 移动蛇头
            Body[0].Position = newHeadPosition;
        }

        /// <summary>
        /// 根据当前方向获取新的蛇头位置
        /// </summary>
        private Point GetNewHeadPosition(Point currentHead)
        {
            switch (Direction)
            {
                case Direction.Up:
                    return new Point(currentHead.X, currentHead.Y - 1);
                case Direction.Down:
                    return new Point(currentHead.X, currentHead.Y + 1);
                case Direction.Left:
                    return new Point(currentHead.X - 1, currentHead.Y);
                case Direction.Right:
                    return new Point(currentHead.X + 1, currentHead.Y);
                default:
                    return currentHead;
            }
        }

        /// <summary>
        /// 增长蛇身
        /// </summary>
        public void Grow()
        {
            // 在蛇尾添加新节点
            Point tailPosition = Body[Body.Count - 1].Position;
            Body.Add(new SnakeNode(tailPosition));
        }

        /// <summary>
        /// 检查是否撞到自己
        /// </summary>
        public bool IsCollidingWithSelf()
        {
            Point headPosition = Body[0].Position;
            for (int i = 1; i < Body.Count; i++)
            {
                if (Body[i].Position == headPosition)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 检查是否撞墙
        /// </summary>
        public bool IsCollidingWithWall(int gameWidth, int gameHeight)
        {
            Point headPosition = Body[0].Position;
            return headPosition.X < 0 || headPosition.X >= gameWidth ||
                   headPosition.Y < 0 || headPosition.Y >= gameHeight;
        }

        /// <summary>
        /// 检查是否吃到食物
        /// </summary>
        public bool IsEatingFood(Point foodPosition)
        {
            return Body[0].Position == foodPosition;
        }

        /// <summary>
        /// 检查是否可以改变方向
        /// </summary>
        public bool CanChangeDirection(Direction newDirection)
        {
            // 不能直接反向移动
            return (Direction == Direction.Up && newDirection != Direction.Down) ||
                   (Direction == Direction.Down && newDirection != Direction.Up) ||
                   (Direction == Direction.Left && newDirection != Direction.Right) ||
                   (Direction == Direction.Right && newDirection != Direction.Left);
        }

        /// <summary>
        /// 改变方向
        /// </summary>
        public void ChangeDirection(Direction newDirection)
        {
            if (CanChangeDirection(newDirection))
            {
                NextDirection = newDirection;
            }
        }
    }

    /// <summary>
    /// 食物类
    /// </summary>
    public class Food
    {
        public Point Position { get; set; }
        public bool IsVisible { get; set; }

        public Food()
        {
            IsVisible = false;
        }

        /// <summary>
        /// 生成新的食物
        /// </summary>
        public void Generate(int gameWidth, int gameHeight, List<SnakeNode> snakeBody)
        {
            Random random = new Random();
            Point newPosition;
            bool validPosition;

            do
            {
                validPosition = true;
                newPosition = new Point(random.Next(0, gameWidth), random.Next(0, gameHeight));

                // 检查是否与蛇身重叠
                foreach (var node in snakeBody)
                {
                    if (node.Position == newPosition)
                    {
                        validPosition = false;
                        break;
                    }
                }
            } while (!validPosition);

            Position = newPosition;
            IsVisible = true;
        }

        /// <summary>
        /// 隐藏食物
        /// </summary>
        public void Hide()
        {
            IsVisible = false;
        }
    }

    /// <summary>
    /// 游戏配置类
    /// </summary>
    public class GameConfig
    {
        public int GameWidth { get; set; } = 30; // 游戏区域宽度（格子数）
        public int GameHeight { get; set; } = 20; // 游戏区域高度（格子数）
        public int CellSize { get; set; } = 20; // 每个格子的大小（像素）
        public int GameSpeed { get; set; } = 150; // 游戏速度（毫秒）

        public static GameConfig GetConfigByDifficulty(GameDifficulty difficulty)
        {
            var config = new GameConfig();
            switch (difficulty)
            {
                case GameDifficulty.Easy:
                    config.GameSpeed = 200;
                    break;
                case GameDifficulty.Medium:
                    config.GameSpeed = 150;
                    break;
                case GameDifficulty.Hard:
                    config.GameSpeed = 100;
                    break;
            }
            return config;
        }
    }

    /// <summary>
    /// 排行榜记录类
    /// </summary>
    public class LeaderboardEntry
    {
        public string PlayerName { get; set; }
        public int Score { get; set; }
        public DateTime Date { get; set; }
        public GameDifficulty Difficulty { get; set; }

        public LeaderboardEntry()
        {
            PlayerName = "";
            Score = 0;
            Date = DateTime.Now;
            Difficulty = GameDifficulty.Medium;
        }

        public LeaderboardEntry(string playerName, int score, GameDifficulty difficulty)
        {
            PlayerName = playerName;
            Score = score;
            Date = DateTime.Now;
            Difficulty = difficulty;
        }

        public override string ToString()
        {
            return $"{PlayerName} - {Score}分 ({Date:yyyy-MM-dd HH:mm})";
        }
    }

    /// <summary>
    /// 排行榜管理类
    /// </summary>
    public class Leaderboard
    {
        private List<LeaderboardEntry> entries;
        private readonly string leaderboardFile = "leaderboard.txt";
        private const int MaxEntries = 10; // 最多保存10条记录

        public List<LeaderboardEntry> Entries => entries.OrderByDescending(e => e.Score).Take(MaxEntries).ToList();

        public Leaderboard()
        {
            entries = new List<LeaderboardEntry>();
            LoadLeaderboard();
        }

        /// <summary>
        /// 添加新记录
        /// </summary>
        public void AddEntry(string playerName, int score, GameDifficulty difficulty)
        {
            var entry = new LeaderboardEntry(playerName, score, difficulty);
            entries.Add(entry);
            
            // 按分数排序并只保留前MaxEntries条记录
            entries = entries.OrderByDescending(e => e.Score).Take(MaxEntries).ToList();
            
            SaveLeaderboard();
        }

        /// <summary>
        /// 检查分数是否足够进入排行榜
        /// </summary>
        public bool IsScoreQualified(int score)
        {
            // 0分不进入排行榜
            if (score <= 0)
                return false;
            
            if (entries.Count < MaxEntries)
                return true;
            
            return score > entries.Min(e => e.Score);
        }

        /// <summary>
        /// 获取指定难度的排行榜
        /// </summary>
        public List<LeaderboardEntry> GetEntriesByDifficulty(GameDifficulty difficulty)
        {
            return entries.Where(e => e.Difficulty == difficulty)
                         .OrderByDescending(e => e.Score)
                         .Take(MaxEntries)
                         .ToList();
        }

        /// <summary>
        /// 加载排行榜
        /// </summary>
        private void LoadLeaderboard()
        {
            try
            {
                if (File.Exists(leaderboardFile))
                {
                    string[] lines = File.ReadAllLines(leaderboardFile);
                    foreach (string line in lines)
                    {
                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            var entry = ParseLeaderboardLine(line);
                            if (entry != null)
                            {
                                entries.Add(entry);
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                entries = new List<LeaderboardEntry>();
            }
        }

        /// <summary>
        /// 保存排行榜
        /// </summary>
        private void SaveLeaderboard()
        {
            try
            {
                var lines = new List<string>();
                foreach (var entry in entries)
                {
                    lines.Add($"{entry.PlayerName}|{entry.Score}|{entry.Date:yyyy-MM-dd HH:mm:ss}|{(int)entry.Difficulty}");
                }
                File.WriteAllLines(leaderboardFile, lines);
            }
            catch (Exception)
            {
                // 保存失败时不抛出异常
            }
        }

        /// <summary>
        /// 解析排行榜行
        /// </summary>
        private LeaderboardEntry ParseLeaderboardLine(string line)
        {
            try
            {
                var parts = line.Split('|');
                if (parts.Length == 4)
                {
                    var entry = new LeaderboardEntry();
                    entry.PlayerName = parts[0];
                    
                    if (int.TryParse(parts[1], out int score))
                        entry.Score = score;
                    
                    if (DateTime.TryParse(parts[2], out DateTime date))
                        entry.Date = date;
                    
                    if (int.TryParse(parts[3], out int difficulty))
                        entry.Difficulty = (GameDifficulty)difficulty;
                    
                    return entry;
                }
            }
            catch (Exception)
            {
                // 解析失败时返回null
            }
            
            return null;
        }
    }
} 